/*
var fs = require('fs');
var vm = require('vm');
var includeInThisContext = function(path) {
    var code = fs.readFileSync(path);
    vm.runInThisContext(code, path);
}.bind(this);
includeInThisContext(__dirname+"/models/car.js");
*/
var serverHost = "psytouch";
var serverPublic = "http://"+serverHost+"/uist/web/server/public/";
var fs = require('fs');
var http = require('http');
var realBinaryTransfer = false;

// Serve client side statically
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/'));

var server = http.createServer(app);

// Start Binary.js server
var BinaryServer = require('binaryjs').BinaryServer;
var bs = BinaryServer({server: server});
var file;
var fileName;
var fileExit;
var fileVal;
var keepAlive = 2000;
var clients = [];
var waiterRecieve = {};
var waiterSend = {};
var actives = {};
var RECIEVER = 0;
var SENDER = 1;

// Wait for new user connections
bs.on('error',function(error){});
bs.on('connection', function(client){
  // Incoming stream from browsers
  console.log(client.id+' se conecto');
  
  console.log(client.id+' informa a '+bs.clients.length+' usuarios que se conecto');
  broadCast(client,{method:'userConnected',value:client.id});
  
  client.on('error', function(error){});
  client.on('close', function(){
	console.log(client.id+' salio');
    console.log(client.id+' informa a '+bs.clients.length+' usuarios que se conecto');
    broadCast(client,{method:'userDisconnected',value:client.id});
  });
  client.on('open', function(){});
  client.on('stream', function(stream, meta){
    //
	if(meta)
	{
		if(meta.method=='sendFile')
		{
			stream.on('pause',function(){});
			stream.on('resume',function(){});
			stream.on('end',function(){
				if(stream["toClient"]!=null)
				{
					fileExit = fs.createReadStream(fileName);
					console.log(this["toClient"]+' esta bajando de servidor');
					bs.clients[this["toClient"]].send(fileExit,{method:'recieveFile'});
				}
				else if(meta.external)
				{
					fileExit = fs.createReadStream(fileName);
					var imageUrl = serverPublic;
					var fileExt = fileName.split('.').pop();
					switch(fileExt)
					{
						case "jpg":
						case "png":
						case "gif":
							imageUrl += fileVal;
							break;
						default:
							if(fs.existsSync(fileName+'.png'))
							{
								imageUrl += fileVal+'.png';
							}
							else
							{
								if(fs.existsSync("types/"+fileExt+".png"))
								{
									imageUrl += "types/"+fileExt+".png";
								}
								else
								{
									imageUrl += "types/file.png";
								}
							}
							break;
					}
					var paramsRecieve = {method:'recieveFile',fileExt:fileExt,fileName:fileVal,imageUrl:imageUrl,url:serverPublic+fileVal};
					if(realBinaryTransfer)
					{
						client.send(fileExit,paramsRecieve);
					}
					else
					{
						client.send({},paramsRecieve);
					}
				}
			});
			stream.on('close',function(){});
			stream.on('drain',function(){});
			stream.on('error',function(error){});
			
			stream["toClient"] = meta.extra!=null?meta.extra:getPossibleUser(RECIEVER,client.id);
			if(stream["toClient"] != null)
			{
				console.log(client.id+' esta subiendo a servidor para despues enviarselo a '+stream["toClient"]);
				fileVal = meta.name;
				fileName = __dirname+ '/public/' + meta.name;
				if(realBinaryTransfer)
				{
					file = fs.createWriteStream(fileName);
					stream.pipe(file);
					//
					// Send progress back
					stream.on('data', function(data){
					  stream.write({rx: data.length / meta.size});
					});
				}
				else
				{
					var paramsRecieve = {method:'recieveFile',fileExt:meta.fileExt,fileName:meta.name,imageUrl:meta.imageUrl,url:meta.fileUrl};
					console.log(paramsRecieve);
					bs.clients[stream["toClient"]].send({},paramsRecieve);
				}
			}
			else if(meta.external)
			{
				console.log(client.id+' esta subiendo a servidor para visualizarlo');
				fileVal = meta.name;
				fileName = __dirname+ '/public/' + meta.name;
				file = fs.createWriteStream(fileName);
				stream.pipe(file);
				//
				// Send progress back
				stream.on('data', function(data){
				  stream.write({rx: data.length / meta.size});
				});
			}
			else
			{
				console.log(client.id+' espera enviar su archivo');
				waiterSend[client.id] = (new Date()).getTime();
				client.send({},{method:'serverWaiting',value:'OK'});
			}

		}
		else if(meta.method=="clientWaiting")
		{			
			var senderClient = getPossibleUser(SENDER,client.id);
			
			if(senderClient!=null)
			{
				console.log(client.id+' se emparejo con '+senderClient);
				bs.clients[senderClient].send({},{method:'sendRequest',value:client.id});
				client.send({},{method:'connectedTo',value:senderClient});
			}
			else
			{
				console.log(client.id+' espera que le envien un archivo');
				waiterRecieve[client.id] = (new Date()).getTime();
				client.send({},{method:'clientWaiting',value:'OK'});
			}
		}
		else if(meta.method=="clientListRequest")
		{
			var arrClients = [];
			for(var i in bs.clients)
			{
				if(bs.clients[i].id != client.id)
				{
					arrClients.push(bs.clients[i].id);
				}
			}
			console.log(client.id + ' is requesting user list');
			client.send({},{method:'clientListResponse',user:client.id,value:arrClients.join(',')});
		}
	}
    //
  });
});
//
//

function getPossibleUser(clientType,clientId)
{
	var curTime = (new Date()).getTime();
	var exitUser = null;
	if(clientType==RECIEVER)
	{
		waiter = waiterRecieve;
	}
	else
	{
		waiter = waiterSend;
	}
	for(var i in waiter)
	{
		if((curTime-waiter[i])<=keepAlive)
		{
			if(parseInt(i)!=clientId)
			{
				exitUser = parseInt(i);
				delete waiter[i];
				break;
			}
			else
			{
				delete waiter[i];
			}
		}
		else
		{
			delete waiter[i];
		}
	}
	return exitUser;
}

function broadCast(clientCon,data)
{
	for(var i in bs.clients)
	{
		if(bs.clients[i].id != clientCon.id)
		{
			bs.clients[i].send({},data);
		}
	}
}

server.listen(9000);
console.log('HTTP and BinaryJS server started on port 9000');
